package com.ego.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ego.common.constant.SystemConstant;
import com.ego.common.util.PageUtil;
import com.ego.common.util.Result;
import com.ego.common.vo.PageVo;
import com.ego.product.feign.CouponFeign;
import com.ego.product.po.SkuImage;
import com.ego.product.po.SpuInfoDesc;
import com.ego.product.service.*;
import com.ego.product.to.coupon.SeckillSkuInfoTo;
import com.ego.product.vo.DetailVo;
import com.ego.product.vo.SkuFilterConditionVo;
import com.ego.product.vo.SkuFilteredVo;
import com.ego.product.vo.SkuInfoSearchVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ego.product.dao.SkuInfoDao;
import com.ego.product.po.SkuInfo;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author KamTang
 * @program: ego
 * @description sku信息对应实现类
 * @date 2022-11-13 12:56:14
 */
@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfo> implements SkuInfoService {

    @Autowired
    private SkuImageService skuImageService;
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private AttrGroupService attrGroupService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private CouponFeign couponFeign;
    @Autowired
    private ThreadPoolExecutor executor;

    @Override
    public PageVo<SkuInfo> search(SkuInfoSearchVo search) {
        LambdaQueryWrapper<SkuInfo> query = Wrappers.<SkuInfo>lambdaQuery()
                .eq(search.getBrandId() != null && search.getBrandId() != 0, SkuInfo::getBrandId, search.getBrandId())
                .eq(search.getCategoryId() != null && search.getCategoryId() != 0, SkuInfo::getCategoryId, search.getCategoryId());
        if (search.getMaxPrice() != null && search.getMaxPrice().compareTo(BigDecimal.ZERO) > 0) {
            query.le(SkuInfo::getPrice, search.getMaxPrice());
        }
        if (search.getMinPrice() != null && search.getMinPrice().compareTo(BigDecimal.ZERO) > 0) {
            query.ge(SkuInfo::getPrice, search.getMinPrice());
        }
        if (StringUtils.isNotEmpty(search.getKeyword())) {
            query.and(q -> q.like(SkuInfo::getSkuId, search.getKeyword())
                    .or().like(SkuInfo::getSkuName, search.getKeyword())
                    .or().like(SkuInfo::getSkuDesc, search.getKeyword())
                    .or().like(SkuInfo::getSkuTitle, search.getKeyword())
                    .or().like(SkuInfo::getSkuSubtitle, search.getKeyword()));
        }

        Page<SkuInfo> page = this.baseMapper.selectPage(Page.of(search.getPageNum(), search.getPageSize()), query);
        return PageUtil.toPage(page);
    }

    @Override
    public List<SkuFilteredVo> filter(SkuFilterConditionVo filter) {
        return this.baseMapper.filter(filter.getCategoryId(), filter.getBrandId());
    }

    @Override
    public List<SkuInfo> getBySpuId(Long spuId) {
        return this.baseMapper.selectList(new QueryWrapper<SkuInfo>().eq("spu_id", spuId));
    }

    @Override
    public DetailVo detail(Long skuId) throws ExecutionException, InterruptedException {
        DetailVo detail = new DetailVo();

        // sku基本信息：pms_sku_info
        CompletableFuture<SkuInfo> skuInfoTask = CompletableFuture
                .supplyAsync(() -> {
                    SkuInfo skuInfo = this.getById(skuId);
                    detail.setSkuInfo(skuInfo);
                    return skuInfo;
                }, executor);

        // spu销售属性组合：
        CompletableFuture<Void> saleAttrsTask = skuInfoTask.thenAcceptAsync((skuInfo) -> {
            List<DetailVo.DetailSaleAttrVo> saleAttrs = skuSaleAttrValueService.getBySpuId(skuInfo.getSpuId());
            detail.setSaleAttrs(saleAttrs);
        }, executor);

        // spu介绍：
        CompletableFuture<Void> spuDescriptionTask = skuInfoTask.thenAcceptAsync((skuInfo) -> {
            SpuInfoDesc spuInfoDesc = spuInfoDescService.getById(skuInfo.getSpuId());
            detail.setDescription(spuInfoDesc);
        }, executor);

        // 规格参数信息：
        CompletableFuture<Void> attrGroupsTask = skuInfoTask.thenAcceptAsync((skuInfo) -> {
            List<DetailVo.DetailSpuAttrGroupVo> spuAttrGroups = attrGroupService
                    .withAttrsBySpuId(skuInfo.getSpuId(), skuInfo.getCategoryId());
            detail.setAttrGroups(spuAttrGroups);
        }, executor);

        // sku图片信息：pms_sku_images
        CompletableFuture<Void> skuImageTask = CompletableFuture.runAsync(() -> {
            List<SkuImage> skuImages = skuImageService.gets(skuId);
            detail.setSkuImages(skuImages);
        }, executor);

        // 秒杀优惠
        CompletableFuture<Void> seckillSkuTask = CompletableFuture.runAsync(() -> {
            Result seckillSkuResp = couponFeign.getSeckillSku(skuId);
            if (seckillSkuResp.getCode() == SystemConstant.Status.SUCCESS.getCode()) {
                SeckillSkuInfoTo seckillSkuInfoTo = seckillSkuResp.getData(new TypeReference<SeckillSkuInfoTo>() {
                });
                detail.setSeckillSkuInfoTo(seckillSkuInfoTo);
            } else {
                detail.setSeckillSkuInfoTo(null);
            }
        }, executor);

        // 这里的get是利用阻塞等待线程完成任务，不关心异常，有就是业务中的异常。
        CompletableFuture.allOf(saleAttrsTask, spuDescriptionTask, attrGroupsTask, skuImageTask, seckillSkuTask).get();

        return detail;
    }
}
